# Filters added to this controller apply to all controllers in the application.
# Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
  helper :all # include all helpers, all the time
  protect_from_forgery # See ActionController::RequestForgeryProtection for details

  # Scrub sensitive parameters from your log
  # filter_parameter_logging :password
  
  private
  
  #
  # TA note:
  # Provided method for building a graphviz graph. 
  # You may want to change this method to alter the appearance of your 
  # visualization.
  # Fairly scant documentation for ruby-graphviz:
  # http://ruby-asp.rubyforge.org/ruby-graphviz/classes/GraphViz.html
  # graphviz constants: https://labs.riseup.net/code/repositories/entry/crabgrass/vendor/plugins/ruby-graphviz-0.9.0/lib/graphviz/constants.rb?rev=61d777e177a996f55c7e670e0033cf39e424d8b8
  # NOTE: if you find a better resource on the web, please post to class mailing list
  def build_graph(links)
    #
    # TA note: trying out different layout methods
    #    g = GraphViz::new("EnronGraph", :use => "dot")
    #    g = GraphViz::new("EnronGraph", :use => "twopi")
    # force directed layout looks best
    g = GraphViz::new("EnronGraph", :use => "fdp")

    # set global node options
    g.node[:color]    = "#ddaa66"
    g.node[:style]    = "filled"
    g.node[:shape]    = "oval"
    g.node[:penwidth] = "1"
    g.node[:fontname] = "Trebuchet MS"
    g.node[:fontsize] = "12"
    g.node[:fillcolor]= "#ffeecc"
    g.node[:fontcolor]= "#775500"
    g.node[:margin]   = "0.05"

    # set global edge options
    g.edge[:color]    = "#999999"
    g.edge[:weight]   = "1"
    g.edge[:fontsize] = "6"
    g.edge[:fontcolor]= "#444444"
    g.edge[:fontname] = "Verdana"
    g.edge[:dir]      = "forward"
    g.edge[:arrowsize]= "0.5"

    #
    # TA note:
    # calls the helper method that creates the nodes and edges
    #add_links_naive(g, links)
    #add_links_limited(g, links)
    add_links_awesome(g, links)
    
    #
    # TA note:
    # saves graph image in instance variable, accessible from front end
    # see access to @graph_path in enron/app/views/terms/search.html.erb 
    @graph_path = "graph/graph-" << Time.now.to_s.gsub(/[\W]/, '') <<".png"
    internal_path = "public/" << @graph_path
    g.output("output" => "png", :file => internal_path)    
  end

  #
  # TA note:
  # this method makes a graph that could be too big
  # we don't use it
  #
  def add_links_naive(g, links)
    links.each do |link|
      unless link.e_from == nil or link.e_to == nil
        #puts 'now processing ' << link.e_from << " - "<< link.e_to
        from = "\"" << link.e_from.split('@', 2)[0] << "\""
        to = "\"" << link.e_to.split('@', 2)[0] << "\""
        g.add_node(from)
        g.add_node(to)
        g.add_edge(from, to)
      end
    end
  end
  
  #
  # TA note:
  # this method makes a graph that is limited to 100 nodes, not very good
  # either
  def add_links_limited(g, links)
    if (links.size >= 100)
      links = links[0..99]
    end
    @graph_label = "size-limited visualization: #{links.size}"
    puts @graph_label
    links.each do |link|
      unless link.e_from == nil or link.e_to == nil
        #puts 'now processing ' << link.e_from << " - "<< link.e_to
        from = "\"" << link.e_from.split('@', 2)[0] << "\""
        to = "\"" << link.e_to.split('@', 2)[0] << "\""
        g.add_node(from)
        g.add_node(to)
        g.add_edge(from, to)
      end
    end
  end
  
  def add_links_awesome(g, links)    
    # maps recipient names to sender names
    recipients = {}
    links.each do |link|
      unless link.e_from == nil or link.e_to == nil
        from = "\"" << link.e_from.split('@', 2)[0] << "\""
        to = "\"" << link.e_to.split('@', 2)[0] << "\""
        recipients[to] = [] unless recipients[to]
        recipients[to] << from unless from == to
      end
    end
    # each element of the array is an array
    # the first element of each element array is the recipient and the others are senders
    limited_recipients = recipients.keys.map{|key| [key] + recipients[key]}.sort{|a,b| b.length <=> a.length}
    limited_recipients.each do |recipient|
      to = recipient[0]
      node = g.add_node(to)
      
      if recipient.length > 4
        node.set do |n|
          n.fillcolor = n.color = "#ff0000"
          n.fontcolor = "#ffffff"
          n.fontsize = "14"
        end
      end
      
      return if graph_full?(g)
      recipient[1..-1].each do |from|
        g.add_node(from)
        g.add_edge(from, to)
        return if graph_full?(g)
      end
    end
  end
  
  def graph_full?(g)
    @graph_label = "# of nodes: #{g.node_count()} (limited to 100)"
    puts @graph_label
    g.node_count() == 100
  end
  
  #
  # TA note:
  # Provided helper method. You'll probably want to call it during inverted
  # index creation
  #  
  def parse_words(text)
    d = []
    unless text.blank?
      # remove any char that's not a letter, digit or space
      words = text.gsub(/[^\w\s]/," ").split  
      words.each do |word|
        unless word.size < 2 or word.size > 50
          d << word.downcase
        end
      end
    end
    return d
  end

end
